<template>
  <div class="form-edit-container">
    <div class="left-board">
      <el-scrollbar class="left-scrollbar">
        <div class="components-list">
          <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
            <div class="components-title">
              {{ item.title }}
            </div>
            <draggable
              :clone="cloneComponent"
              :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
              :list="item.list"
              :move="handleMove"
              :sort="false"
              class="components-draggable"
              draggable=".components-item"
              :force-fallback="true"
              :scroll="true"
              :scroll-sensitivity="160"
              @end="onEnd"
            >
              <div
                v-for="(element, index) in item.list"
                :key="index"
                class="components-item"
                @click="addComponent(element)"
              >
                <div class="components-body">
                  <form-svg-icon :name="element.config.tagIcon" />
                  {{ element.config.label }}
                </div>
              </div>
            </draggable>
          </div>
        </div>
      </el-scrollbar>
    </div>
    <div class="center-board">
      <el-row class="operation-btn-view" type="flex" align="middle">
        <el-col :span="12" class="text-base-color small-font-size">
          * 表单内容自动保存
          <i :class="showLoading ? 'el-icon-loading' : 'el-icon-check'"></i>
        </el-col>
        <el-col :span="4" class="import-topic-box">
          <el-button type="text" icon="el-icon-top" @click="handleOpenImportItem"> 导入题目 </el-button>
          <!--          <el-button
            icon="el-icon-postcard"
            class="template-text"
            v-hasPermi="['form:template:save']"
            type="text"
            @click="saveProjectAsTemplateHandle"
          >
            保存为模板
          </el-button>-->
        </el-col>
      </el-row>
      <ImportFormItem ref="importItems" :form-key="formKey" @success="queryProjectItems" />
      <el-scrollbar ref="centerScrollbar" class="center-scrollbar">
        <el-row v-if="formConf" :gutter="formConf.gutter" class="center-board-row">
          <div v-if="formConf.type == 4" class="evaluation-total-score">
            <div class="total-score-title">总分</div>
            <div class="total-score">
              {{ totalScore }}
            </div>
          </div>
          <el-row class="center-name-box" align="middle" justify="center" type="flex">
            <el-col class="text-center" :span="21">
              <form-tinymce
                :inline="true"
                :value="formConf.title"
                @input="
                  (val) => {
                    this.formConf.title = val
                    this.saveProjectInfo()
                  }
                "
              />
            </el-col>
          </el-row>
          <el-row class="center-desc-box" align="middle" justify="center" type="flex">
            <el-col :span="21">
              <form-tinymce
                :inline="true"
                :value="formConf.description"
                @input="
                  (val) => {
                    this.formConf.description = val
                    this.saveProjectInfo()
                  }
                "
              />
            </el-col>
          </el-row>
          <el-divider />
          <el-form
            :label-position="formConf.labelPosition"
            :label-width="formConf.labelWidth + 'px'"
            :size="formConf.size"
          >
            <draggable
              :animation="180"
              :list="drawingList"
              :move="handleCenterMove"
              class="drawing-board"
              group="componentsGroup"
              handle=".mover"
              :force-fallback="true"
              :scroll="true"
              :scroll-sensitivity="160"
              @end="onItemEnd"
            >
              <form-item-layout
                v-for="(item, index) in drawingList"
                :key="item.renderKey"
                :active-id="activeId"
                :current-item="item"
                :drawing-list="drawingList"
                :form-conf="formConf"
                :index="index"
                @activeItem="activeFormItem"
                @change="updateProjectItemInfo"
                @changeLabel="changeLabel"
                @copyItem="drawingItemCopy"
                @deleteItem="drawingItemDelete"
              />
            </draggable>
            <div v-show="!drawingList.length" class="empty-info">
              <img
                src=""
              />
              <p>从左侧拖入或点选组件进行表单设计</p>
            </div>
          </el-form>
        </el-row>
      </el-scrollbar>
    </div>
    <template-create ref="templateCreate" :form-key="formKey" />
    <right-panel
      :active-data="activeData"
      :form-conf="formConf"
      :fields="drawingList"
      :show-field="!!drawingList.length"
      @tag-change="tagChange"
      @add-fields="handleAddFields"
      @data-change="handleActiveDataChange"
    />
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import TemplateCreate from '@/views/project/template/create'
import FormItemLayout from './FormItemLayout'
import RightPanel from './RightPanel'
import FormTinymce from '../tinymce'
import FormSvgIcon from '../../components/SvgIcon/index'
import ImportFormItem from './ImportFormItem'
import { debounce } from 'throttle-debounce'
import { getAllComponents, getComponentsObj, getFormConfig } from '../GenerateForm/config'
import _ from 'lodash'
import '../../assets/icons'
import { deepClone, jsonSimpleClone, removeHtmlTag } from '../../utils'
import { dbDataConvertForItemJson, formItemConvertData } from '../../utils/convert'
import {
  createProjectItem,
  deleteProjectItem,
  queryProject,
  queryProjectItemList,
  sortProjectItem,
  stopPublishFormRequest,
  updateProject,
  updateProjectItem
} from '../../api'

let oldActiveId
let tempActiveData

export default {
  name: 'FormEditor',
  components: {
    TemplateCreate,
    FormTinymce,
    FormItemLayout,
    draggable,
    RightPanel,
    FormSvgIcon,
    ImportFormItem
  },
  data() {
    return {
      showLoading: false,
      showPublishConfirm: false,
      formConf: null,
      tempFormConf: {},
      labelWidth: 100,
      drawingList: [],
      activeId: 0,
      activeData: null,
      formKey: null
    }
  },
  computed: {
    leftComponents() {
      this.showLoading = false
      return getAllComponents(this.tempFormConf.type)
    },
    totalScore() {
      let total = 0
      this.drawingList.forEach((item) => {
        if (item.examConfig && item.examConfig.score) {
          total += item.examConfig.score
        }
      })
      // 如果有小数 保留一位小数
      if (Number.isInteger(total)) {
        return total
      } else {
        return Math.fround(total).toFixed(2)
      }
    }
  },
  watch: {
    'activeData.config.label': function (val, oldVal) {
      if (this.activeData.placeholder === undefined || !this.activeData.config.tag || oldActiveId !== this.activeId) {
        return
      }
      this.activeData.placeholder = this.activeData.placeholder.replace(removeHtmlTag(oldVal), '') + removeHtmlTag(val)
    },
    activeId: {
      handler(val) {
        oldActiveId = val
      },
      immediate: true
    }
  },
  mounted() {
    // 复制对象 避免修改改变原始对象
    this.formConf = JSON.parse(JSON.stringify(getFormConfig(this.$route.query.type)))
    // 项目key
    this.formKey = this.$route.query.key
    this.formConf.formKey = this.formKey
    // 从服务端获取
    this.queryProjectItems()
    this.queryProject()
  },
  methods: {
    saveProjectAsTemplateHandle() {
      this.$refs['templateCreate'].handleOpen()
    },
    // 获取表单配置
    queryProject() {
      queryProject(this.formKey).then((res) => {
        this.tempFormConf = res.data
        this.formConf.title = res.data.name
        this.formConf.type = res.data.type
        if (res.data.description) {
          this.formConf.description = res.data.description
        }
      })
    },
    //更新标题和描述
    saveProjectInfo: debounce(200, true, function () {
      this.showLoading = true
      updateProject({
        formKey: this.formKey,
        name: this.formConf.title,
        description: this.formConf.description
      }).then(() => {
        this.showLoading = false
      })
    }),
    // 处理已经发布的表单
    async handleCheckPublicForm() {
      let noPublish = true
      if (this.tempFormConf.status == 2 && !this.showPublishConfirm) {
        noPublish = false
        this.showPublishConfirm = true
        await this.$confirm('该表单已发布，继续编辑将会停止发布，是否确认？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        })
          .then(async () => {
            await stopPublishFormRequest({ formKey: this.formKey })
            await this.queryProject()
            noPublish = true
          })
          .catch(() => {
            noPublish = false
          })
          .finally(() => {
            this.showPublishConfirm = false
          })
      }
      return noPublish
    },
    handleActiveDataChange(val) {
      // 特殊处理子表单 使修改的数据为子表单组件本身
      let copyValue = jsonSimpleClone(val)
      if (val.isChild) {
        let parentItem = val.parentItem
        let tempVal = deepClone(val)
        delete tempVal.parentItem
        delete tempVal.childIndex
        parentItem.childList[val.childIndex] = tempVal
        let tempParVal = jsonSimpleClone(parentItem)
        tempParVal.childList.forEach((item) => {
          delete item.parentItem
        })
        copyValue = tempParVal
      }
      this.updateProjectItemInfo(copyValue)
    },
    updateProjectItemInfo: debounce(100, true, function (val) {
      this.showLoading = true
      const data = formItemConvertData(val, this.formKey)
      updateProjectItem(data).then(() => {
        this.showLoading = false
      })
    }),
    async deleteProjectItemInfo(val) {
      this.showLoading = true
      const data = formItemConvertData(val, this.formKey)
      try {
        await deleteProjectItem(data)
        return true
      } catch (e) {
        return false
      } finally {
        this.showLoading = false
      }
    },
    async saveProjectItemInfo(item) {
      this.showLoading = true
      let isSuccess = false
      const params = formItemConvertData(item, this.formKey)
      const pItem = item
      await createProjectItem(params).then((res) => {
        this.showLoading = false
        pItem.sort = res.data.sort
        isSuccess = true
      })
      // 如果是分页组件 刷新所有分页的页码
      if (item.typeId === 'PAGINATION') {
        this.updatePaginationList()
      }
      return isSuccess
    },
    updatePaginationList() {
      // 页总数
      const { length } = this.drawingList.filter((item) => item.typeId === 'PAGINATION')
      let curr = 1
      this.drawingList.forEach((item, index) => {
        if (item.typeId === 'PAGINATION') {
          item.totalPageNum = length
          item.currPageNum = curr++
          this.$set(this.drawingList, index, item)
        }
      })
    },
    queryProjectItems() {
      queryProjectItemList({ key: this.formKey }).then((res) => {
        this.drawingList = res.data.map((item) => dbDataConvertForItemJson(item))
        // 更新分页
        this.updatePaginationList()
      })
    },
    activeFormItem(currentItem) {
      this.activeData = currentItem
      this.activeId = currentItem.config.formId
    },
    changeLabel(currentItem, value) {},
    handleMove(e, originalEvent) {
      if (this.tempFormConf.status == 2) {
        this.handleCheckPublicForm()
        return false
      }
      return true
    },
    onEnd(obj) {
      if (obj.from !== obj.to) {
        this.activeData = tempActiveData
        this.activeId = `${_.toLower(tempActiveData.typeId)}-${new Date().getTime()}`
        // 拖拽到子表单不单独保存
        if (obj.to.className === 'list-main') {
          return
        }
        this.saveProjectItemInfo(tempActiveData).then(() => {
          this.onItemEnd(obj, true)
        })
      }
    },
    handleCenterMove(obj) {
      // 不允许拖到子表单
      if (obj.to.className === 'list-main') {
        return false
      }
    },
    onItemEnd(obj, createNew = false) {
      this.showLoading = true
      // createNew 避免新的组件拉到第一个不排序
      if (obj.oldIndex === obj.newIndex && !createNew) {
        this.showLoading = false
        return
      }
      const params = { formKey: this.formKey }
      if (this.drawingList[obj.newIndex - 1]) {
        params.beforePosition = this.drawingList[obj.newIndex - 1].sort
      }
      if (this.drawingList[obj.newIndex + 1]) {
        params.afterPosition = this.drawingList[obj.newIndex + 1].sort
      }
      params.formItemId = this.drawingList[obj.newIndex].config.formId
      if (params.beforePosition || params.afterPosition) {
        sortProjectItem(params).then((res) => {
          this.drawingList[obj.newIndex].sort = res.data.sort
          if (res.data.refreshAll) {
            this.queryProjectItems()
          }
          this.showLoading = false
        })
      } else {
        this.showLoading = false
      }
    },
    addComponent(item) {
      debugger
      console.log('addComponent')
      this.handleCheckPublicForm().then((res) => {
        if (res) {
          const clone = this.cloneComponent(item)
          this.saveProjectItemInfo(clone)
          this.drawingList.push(clone)
          this.activeFormItem(clone)
          // 滑动定位到底部
          this.scrollToBottom()
        }
      })
    },
    scrollToBottom() {
      const div = this.$refs.centerScrollbar.$refs.wrap
      this.$nextTick(() => {
        div.scrollTop = div.scrollHeight
      })
    },
    cloneComponent(origin) {
      const clone = deepClone(origin)
      const config = clone.config
      this.createIdAndKey(clone)

      // 文件上传组件处理
      if (clone.action) {
        clone.action += this.formKey
      }
      clone.placeholder !== undefined && (clone.placeholder += config.label)
      tempActiveData = clone
      return tempActiveData
    },
    createIdAndKey(item) {
      const config = item.config
      // 使用组件类型+时间戳 为ID
      config.formId = `${_.toLower(item.typeId)}${new Date().getTime()}`
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
      item.vModel = `${config.formId}`
      return item
    },
    empty() {
      this.$confirm('确定要清空所有组件吗？', '提示', { type: 'warning' }).then(() => {
        this.drawingList = []
      })
    },
    drawingItemCopy(item, list) {
      this.handleCheckPublicForm().then((res) => {
        if (res) {
          let clone = deepClone(item)
          clone = this.createIdAndKey(clone)
          list.push(clone)
          this.activeFormItem(clone)
          this.saveProjectItemInfo(clone)
        }
      })
    },
    async drawingItemDelete(item, list) {
      // this.handleCheckPublicForm().then((res) => {
      //   if (res) {
      const isSuccess = await this.deleteProjectItemInfo(item)
      if (isSuccess) {
        const index = list.findIndex((val) => val.config.formId === item.config.formId)
        list.splice(index, 1)
        this.$nextTick(() => {
          const len = this.drawingList.length
          if (len) {
            this.activeFormItem(this.drawingList[len - 1])
          }
        })
      }

      // }
      // })
    },
    // 类型切换 弃用
    tagChange(newTag) {
      newTag = this.cloneComponent(newTag)
      const config = newTag.config
      newTag.vModel = this.activeData.vModel
      newTag.sort = this.activeData.sort
      config.formId = this.activeId
      config.span = this.activeData.config.span
      this.activeData.config.tag = config.tag
      this.activeData.config.tagIcon = config.tagIcon
      this.activeData.config.document = config.document
      this.activeData.typeId = newTag.typeId
      if (typeof this.activeData.config.defaultValue === typeof config.defaultValue) {
        config.defaultValue = this.activeData.config.defaultValue
      }
      Object.keys(newTag).forEach((key) => {
        if (this.activeData[key] !== undefined) {
          newTag[key] = this.activeData[key]
        }
      })
      this.activeData = newTag
      this.updateProjectItemInfo(newTag)
      this.updateDrawingList(newTag, this.drawingList)
    },
    updateDrawingList(newTag, list) {
      const index = list.findIndex((item) => item.config.formId === this.activeId)
      if (index > -1) {
        list.splice(index, 1, newTag)
      } else {
        list.forEach((item) => {
          if (Array.isArray(item.config.children)) this.updateDrawingList(newTag, item.config.children)
        })
      }
    },
    handleOpenImportItem() {
      this.$refs.importItems.showDialog()
    },
    // 创建Ocr识别所需要的存储字段 由Ocr字段抛出
    handleAddFields(val) {
      //创建字段 保存识别返回字段和表单字段映射关系
      let fieldMapping = {}
      _.keys(val).forEach((key) => {
        let field = val[key]
        let compo = jsonSimpleClone(getComponentsObj()[field.type])
        compo.config.label = field.label
        const clone = this.cloneComponent(compo)
        this.saveProjectItemInfo(clone)
        this.drawingList.push(clone)
        fieldMapping[key] = clone.config.formId
      })
      this.activeData.fieldMapping = fieldMapping
      // 保存
      this.handleActiveDataChange(this.activeData)
    }
  }
}
</script>

<style lang="scss">
@import '../../assets/styles/home.scss';
@import '../../assets/styles/index.scss';
.template-text {
  margin-left: 20px !important;
}
</style>
